package com.kerbores.jongo.marshall.nutz;

import java.lang.reflect.Field;
import java.util.Map;

import org.nutz.json.Json;
import org.nutz.lang.Lang;
import org.nutz.log.Log;
import org.nutz.log.Logs;

import com.kerbores.jongo.ObjectIdUpdater;
import com.kerbores.jongo.bson.Bson;
import com.kerbores.jongo.bson.BsonDocument;
import com.kerbores.jongo.marshall.Marshaller;
import com.kerbores.jongo.marshall.MarshallingException;
import com.kerbores.jongo.marshall.Unmarshaller;
import com.mongodb.BasicDBObject;

/**
 * @author 王贵源<kerbores>
 *
 *         create at 2015年12月21日 下午5:03:01
 */
public class NutzMarshallerEngine implements Unmarshaller, Marshaller {

	ObjectIdUpdater updater = new NutzObjectIdUpdater(IdFieldSelector.defaultiIdFieldSelector);
	Log log = Logs.get();

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.jongo.marshall.Marshaller#marshall(java.lang.Object)
	 */
	@Override
	public BsonDocument marshall(Object pojo) throws MarshallingException {
		if (updater.mustGenerateObjectId(pojo)) {
			Map map = Lang.map(Json.toJson(pojo));
			BasicDBObject dbo = new BasicDBObject(map);
			return Bson.createDocument(dbo);
		}

		Map map = Lang.map(Json.toJson(pojo));
		map.remove(updater.getIdField(pojo).getName());
		map.put("_id", updater.getId(pojo));
		BasicDBObject dbo = new BasicDBObject(map);
		return Bson.createDocument(dbo);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.jongo.marshall.Unmarshaller#unmarshall(org.jongo.bson.BsonDocument,
	 * java.lang.Class)
	 */
	@Override
	public <T> T unmarshall(BsonDocument document, Class<T> clazz) throws MarshallingException {
		Map map = document.toDBObject().toMap();
		T t = Lang.map2Object(map, clazz);
		if (updater.mustGenerateObjectId(t)) {
			return t;
		}

		Field f = updater.getIdField(t);
		f.setAccessible(true);
		try {
			f.set(t, map.get("_id"));
		} catch (IllegalArgumentException e) {
			log.error(e);
		} catch (IllegalAccessException e) {
			log.error(e);
		}
		return t;
	}
}
